package znet

import (
	"fmt"
	"strconv"
	ziface "zinx/Ziface"
	"zinx/utlis"
)

type MsgHandler struct {

	//根据Msgid管理路由模块
	Apis map[uint32]ziface.IRouter

	//负责worker取任务的消息队列
	TaskQueue []chan ziface.IRuquest

	//业务工作Worker池的数量
	WorkerPoolsize uint
}

// 执行对应的方法
func (msghd *MsgHandler) DoMsgHandler(request ziface.IRuquest) {
	handler, ok := msghd.Apis[request.GetMsgId()]
	if !ok {
		fmt.Println("api msgid=", request.GetMsgId(), "is not FOUND! Need Register")
		return
	}
	handler.PreHandler(request)
	handler.Handler(request)
	handler.PostHandler(request)
}

// 为消息添加对应的处理逻辑
func (msghd *MsgHandler) AddRouter(msgID uint32, router ziface.IRouter) {
	//如果当前msgid已经被注册
	if _, ok := msghd.Apis[msgID]; ok {
		//如果已经被注册
		panic("repeat api,msgID=" + strconv.Itoa(int(msgID)))
	}
	msghd.Apis[msgID] = router
	fmt.Println("Add api msgID=", msgID, "success!")
}

// 启动一个Worker工作池
func (msghd *MsgHandler) StartWorkerPool() {
	for i := 0; i < int(msghd.WorkerPoolsize); i++ {

		//为chan开辟空间
		msghd.TaskQueue[i] = make(chan ziface.IRuquest, utlis.GlovbalObject.MaxWokerTaskLen)
		//启动一个协程
		go msghd.startWorker(i, msghd.TaskQueue[i])
	}
}

// 启动一个worker工作流程,对内不暴露的方法
func (msghd *MsgHandler) startWorker(workerid int, taskqueue chan ziface.IRuquest) {

	fmt.Println("workerid=", workerid, "is started...")
	for {
		select {
		//从chan中读取对应的request,并执行request
		case re := <-taskqueue:
			msghd.DoMsgHandler(re)
		}
	}
}

// 将Request加入到TaskQueue中
func (msghd *MsgHandler) SendMsgTaskQueue(re ziface.IRuquest) {

	//将消息平均分配给不同的woker
	//根据Connectionid进行分配
	workid := re.GetConnection().GetID() % uint32(msghd.WorkerPoolsize)
	fmt.Println("ADD ConnID:", re.GetConnection().GetID(), "request Msgid=", re.GetMsgId(), "to Workerid=", workid)

	//将请求re,加入到对应worker的chan中
	msghd.TaskQueue[workid] <- re

}

func NewMsgHandler() *MsgHandler {
	return &MsgHandler{
		Apis:           make(map[uint32]ziface.IRouter),
		WorkerPoolsize: utlis.GlovbalObject.WorkerPoolsize,
		TaskQueue:      make([]chan ziface.IRuquest, utlis.GlovbalObject.WorkerPoolsize),
	}
}
